/*!
 * 文件名称： driver_exmc.c
 * 描    述： exmc 驱动文件
 * 版本：     2023-12-03, V1.0
*/

/*
* GD32F303东方红开发板V1.0
* 淘宝商城：   https://juwo.taobao.com
* 技术交流：   https://www.gd32bbs.com/ask/
* 视频学习：   https://space.bilibili.com/475462605
* 微信公众号： gd32bbs
* Copyright    苏州聚沃电子科技有限公司
* 版权所有，盗版必究。
*/

#include "driver_exmc.h"

/*!
* 说明     emxc gpio 初始化
* 输入[1]  无
* 返回值   无
*/
void driver_exmc_gpio_init(void)
{
    /* EXMC clock enable */
    rcu_periph_clock_enable(RCU_EXMC);

    /* EXMC enable */
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_GPIOD);
    rcu_periph_clock_enable(RCU_GPIOE);
    rcu_periph_clock_enable(RCU_GPIOF);
    rcu_periph_clock_enable(RCU_GPIOG);
    rcu_periph_clock_enable(RCU_AF);

    /* configure EXMC_D[0~15]*/
    /* PD14(EXMC_D0), PD15(EXMC_D1),PD0(EXMC_D2), PD1(EXMC_D3), PD8(EXMC_D13), PD9(EXMC_D14), PD10(EXMC_D15) */
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0 | GPIO_PIN_1| GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 |
                                                         GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);

    /* PE7(EXMC_D4), PE8(EXMC_D5), PE9(EXMC_D6), PE10(EXMC_D7), PE11(EXMC_D8), PE12(EXMC_D9), 
       PE13(EXMC_D10), PE14(EXMC_D11), PE15(EXMC_D12) */
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | 
                                                         GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | 
                                                         GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
                                                             

    /* configure NBL0(PE0) and NBL1(PE1) */
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_9 | GPIO_PIN_10);
    
    /* configure NBL0(PE0) and NBL1(PE1) */
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
    
    gpio_compensation_config(GPIO_COMPENSATION_ENABLE);
    
    while(gpio_compensation_flag_get()==RESET);
}



/*!
* 说明     emxc nor/sram模式初始化
* 输入[1]  norsram_region: @EXMC_BANK0_NORSRAM_REGION0/EXMC_BANK0_NORSRAM_REGION1/EXMC_BANK0_NORSRAM_REGION2/EXMC_BANK0_NORSRAM_REGION3
* 返回值   无
*/
void driver_exmc_norsram_init(uint32_t norsram_region)
{
    exmc_norsram_parameter_struct nor_init_struct;
    exmc_norsram_timing_parameter_struct nor_timing_read_init_struct;
    exmc_norsram_timing_parameter_struct nor_timing_write_init_struct;

    /* EXMC clock enable */
    rcu_periph_clock_enable(RCU_EXMC);

    driver_exmc_gpio_init();
    
    
    nor_init_struct.read_write_timing = &nor_timing_read_init_struct;
       
    nor_init_struct.write_timing = &nor_timing_write_init_struct;
    
    exmc_norsram_struct_para_init(&nor_init_struct);
    
    /* config timing parameter */
    nor_timing_read_init_struct.asyn_access_mode = EXMC_ACCESS_MODE_A;
    nor_timing_read_init_struct.syn_data_latency = EXMC_DATALAT_2_CLK;
    nor_timing_read_init_struct.syn_clk_division = EXMC_SYN_CLOCK_RATIO_2_CLK;
    nor_timing_read_init_struct.bus_latency = 1;
    nor_timing_read_init_struct.asyn_data_setuptime = 1;
    nor_timing_read_init_struct.asyn_address_holdtime = 1;
    nor_timing_read_init_struct.asyn_address_setuptime = 1;
    
    /* config timing parameter */
    nor_timing_write_init_struct.asyn_access_mode = EXMC_ACCESS_MODE_A;
    nor_timing_write_init_struct.syn_data_latency = EXMC_DATALAT_2_CLK;
    nor_timing_write_init_struct.syn_clk_division = EXMC_SYN_CLOCK_RATIO_2_CLK;
    nor_timing_write_init_struct.bus_latency = 1;
    nor_timing_write_init_struct.asyn_data_setuptime = 3;
    nor_timing_write_init_struct.asyn_address_holdtime = 1;
    nor_timing_write_init_struct.asyn_address_setuptime = 1;    

    /* config EXMC bus parameters */
    nor_init_struct.norsram_region = norsram_region;
    nor_init_struct.write_mode = EXMC_ASYN_WRITE;
    nor_init_struct.extended_mode = ENABLE;
    nor_init_struct.asyn_wait = DISABLE;
    nor_init_struct.nwait_signal = DISABLE;
    nor_init_struct.memory_write = ENABLE;
    nor_init_struct.nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
    nor_init_struct.wrap_burst_mode = DISABLE;
    nor_init_struct.nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
    nor_init_struct.burst_mode = DISABLE;
    nor_init_struct.databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
    nor_init_struct.memory_type = EXMC_MEMORY_TYPE_SRAM;
    nor_init_struct.address_data_mux = DISABLE;

    exmc_norsram_init(&nor_init_struct);

    /* enable the EXMC bank0 NORSRAM */
    exmc_norsram_enable(norsram_region);   
}

/*!
* 说明     emxc LCD模式通用gpio初始化
* 输入[1]  norsram_region: @EXMC_BANK0_NORSRAM_REGION0/EXMC_BANK0_NORSRAM_REGION1/EXMC_BANK0_NORSRAM_REGION2/EXMC_BANK0_NORSRAM_REGION3
* 返回值   无
*/
void driver_exmc_lcd_16bit_gpio_init(void)
{
    /* EXMC clock enable */
    rcu_periph_clock_enable(RCU_EXMC);

    /* GPIO clock enable */
    rcu_periph_clock_enable(RCU_GPIOD);
    rcu_periph_clock_enable(RCU_GPIOE);
    rcu_periph_clock_enable(RCU_GPIOG);
    rcu_periph_clock_enable(RCU_AF);    

    /* configure EXMC_D[0~15]*/
    /* PD14(EXMC_D0), PD15(EXMC_D1),PD0(EXMC_D2), PD1(EXMC_D3), PD8(EXMC_D13), PD9(EXMC_D14), PD10(EXMC_D15) */
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0 | GPIO_PIN_1| GPIO_PIN_8 | GPIO_PIN_9 |
                                                         GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);

    /* PE7(EXMC_D4), PE8(EXMC_D5), PE9(EXMC_D6), PE10(EXMC_D7), PE11(EXMC_D8), PE12(EXMC_D9), 
       PE13(EXMC_D10), PE14(EXMC_D11), PE15(EXMC_D12) */
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | 
                                                         GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | 
                                                         GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);

//    /* configure PE2(EXMC_Ax) */ 
//    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2);
    
    /* configure NOE and NWE */
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_4 | GPIO_PIN_5);

//    /* configure EXMC NEx */
//    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_7);

    gpio_compensation_config(GPIO_COMPENSATION_ENABLE);
    
    while(gpio_compensation_flag_get()==RESET);
}


/*!
* 说明     emxc LCD模式初始化
* 输入[1]  norsram_region: @EXMC_BANK0_NORSRAM_REGION0/EXMC_BANK0_NORSRAM_REGION1/EXMC_BANK0_NORSRAM_REGION2/EXMC_BANK0_NORSRAM_REGION3
* 返回值   无
*/
void driver_exmc_lcd_init(uint32_t norsram_region)
{
    exmc_norsram_parameter_struct nor_init_struct;
    exmc_norsram_timing_parameter_struct nor_timing_read_init_struct;
    exmc_norsram_timing_parameter_struct nor_timing_write_init_struct;

    /* EXMC clock enable */
    rcu_periph_clock_enable(RCU_EXMC);
    
    nor_init_struct.read_write_timing = &nor_timing_read_init_struct;
       
    nor_init_struct.write_timing = &nor_timing_write_init_struct;    
    
    exmc_norsram_struct_para_init(&nor_init_struct);
    
    /* config timing parameter */
    nor_timing_read_init_struct.asyn_access_mode = EXMC_ACCESS_MODE_A;
    nor_timing_read_init_struct.syn_data_latency = EXMC_DATALAT_2_CLK;
    nor_timing_read_init_struct.syn_clk_division = EXMC_SYN_CLOCK_RATIO_2_CLK;
    nor_timing_read_init_struct.bus_latency = 1;
    nor_timing_read_init_struct.asyn_data_setuptime = 5;
    nor_timing_read_init_struct.asyn_address_holdtime = 1;
    nor_timing_read_init_struct.asyn_address_setuptime = 1;
    
    /* config timing parameter */
    nor_timing_write_init_struct.asyn_access_mode = EXMC_ACCESS_MODE_A;
    nor_timing_write_init_struct.syn_data_latency = EXMC_DATALAT_2_CLK;
    nor_timing_write_init_struct.syn_clk_division = EXMC_SYN_CLOCK_RATIO_2_CLK;
    nor_timing_write_init_struct.bus_latency = 1;
    nor_timing_write_init_struct.asyn_data_setuptime = 2;
    nor_timing_write_init_struct.asyn_address_holdtime = 1;
    nor_timing_write_init_struct.asyn_address_setuptime = 1;    

    /* config EXMC bus parameters */
    nor_init_struct.norsram_region = norsram_region;
    nor_init_struct.write_mode = EXMC_ASYN_WRITE;
    nor_init_struct.extended_mode = ENABLE;
    nor_init_struct.asyn_wait = DISABLE;
    nor_init_struct.nwait_signal = DISABLE;
    nor_init_struct.memory_write = ENABLE;
    nor_init_struct.nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
    nor_init_struct.wrap_burst_mode = DISABLE;
    nor_init_struct.nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
    nor_init_struct.burst_mode = DISABLE;
    nor_init_struct.databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
    nor_init_struct.memory_type = EXMC_MEMORY_TYPE_SRAM;
    nor_init_struct.address_data_mux = DISABLE;

    exmc_norsram_init(&nor_init_struct);

    /* enable the EXMC bank0 NORSRAM */
    exmc_norsram_enable(norsram_region);  
}
